package com.xiaomi.eco.service.impl;

import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.xiaomi.eco.dal.entity.EcoServiceDimensionEntity;
import com.xiaomi.eco.dal.entity.TbEcoApplicationCompanyEntity;
import com.xiaomi.eco.dal.res.EcoServiceRes;
import com.xiaomi.eco.mapper.EcoServiceDimensionEntityMapper;
import com.xiaomi.eco.mapper.TbEcoApplicationCompanyEntityMapper;
import com.xiaomi.eco.service.EcoServiceDimensionEntityService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.web.client.RestTemplate;

import java.io.UnsupportedEncodingException;
import java.net.URI;
import java.net.URLEncoder;
import java.util.List;

@Service
@Slf4j
public class EcoServiceDimensionEntityServiceImpl extends
        ServiceImpl<EcoServiceDimensionEntityMapper, EcoServiceDimensionEntity>
        implements EcoServiceDimensionEntityService {

    private static final double p95timeNum = 47;

    private static final double p99TimeNum = 49;

    private static final String serverEnvValue = "~\".*";
    private static final String serverZoneValue = "~\".*|\"";

    private static final String serverZoneVariablePrefix = "~\"";

    private static final String specialCharacters = "\\s*|\r|\n|\t";
    private static final String horizontalBar = "-";

    private static final String underLine = "_";
    private static final String msPrefix = "http://prometheus-hera.mioffice.cn/api/v1/query?query=";

    private static final String success = "success";
    private static final String p95UrlTemp = "histogram_quantile(0.95,sum(sum_over_time(online_jaeger_aopMethodTimeCount_bucket{application=\"%s\",serverEnv=%s\",serverZone=%s}[1d])) by (le))";

    private static final String p99UrlTemp = "histogram_quantile(0.99,sum(sum_over_time(online_jaeger_aopMethodTimeCount_bucket{application=\"%s\",serverEnv=%s\",serverZone=%s}[1d])) by (le))";

    private static final String totalUrlTemp = "sum(sum_over_time(online_jaeger_aopTotalMethodCount_total{application=\"%s\",serverEnv=%s\",serverZone=%s}[1d]))";

    private static final String errorUrlTemp = "sum(sum_over_time(online_jaeger_httpError_total{application=\"%s\",serverEnv=%s\",serverZone=%s}[1d]))";

    private static final String availabilityUrlTemp = "clamp_min((1 - ((sum(sum_over_time(online_jaeger_httpError_total{application=\"%s\",serverEnv=%s\",serverZone=%s}[1d]))) / (sum(sum_over_time(online_jaeger_aopTotalMethodCount_total{application=\"%s\",serverEnv=%s\",serverZone=%s}[1d]))))), 0) or 0*(sum(sum_over_time(online_jaeger_aopTotalMethodCount_total{application=\"%s\",serverEnv=%s\",serverZone=%s}[1d])))+1";


    @Autowired
    EcoServiceDimensionEntityMapper ecoServiceDimensionEntityMapper;

    @Autowired
    private TbEcoApplicationCompanyEntityMapper tbEcoApplicationCompanyEntityMapper;
    @Autowired
    private RestTemplate restTemplate;

    @Override
    public void insertEcoService() {
        StringBuffer P99Average = new StringBuffer();
        StringBuffer methoAvailability = new StringBuffer();
        StringBuffer P95Average = new StringBuffer();
        StringBuffer totalNum = new StringBuffer();
        ObjectMapper objectMapper = new ObjectMapper();
        StringBuffer errorNum = new StringBuffer();

        List<TbEcoApplicationCompanyEntity> list = tbEcoApplicationCompanyEntityMapper.selectList(null);
        ecoServiceDimensionEntityMapper.deleteByToday();//删除今天的数据
        for (TbEcoApplicationCompanyEntity tbeac : list) {
            String applicationIdName = tbeac.getApplicationId().replaceAll(specialCharacters, "") + underLine + tbeac.getApplicationName().replaceAll(specialCharacters, "").replaceAll(horizontalBar, underLine);
            EcoServiceDimensionEntity ecoServiceDimensionEntity = new EcoServiceDimensionEntity();
            ecoServiceDimensionEntity.setApplicationId(tbeac.getApplicationId());
            ecoServiceDimensionEntity.setCompanyName(tbeac.getCompanyName());
            ecoServiceDimensionEntity.setApplicationName(tbeac.getApplicationName());
            ecoServiceDimensionEntity.setCompanyAbbreviatio(tbeac.getCompanyAbbreviation());


            //调用p95
            P95Average.append(msPrefix);
            String p95Url = "";
            if(tbeac.getServerZone().isEmpty() || tbeac.getServerZone().equals("")){
                 p95Url = String.format(p95UrlTemp, applicationIdName, serverEnvValue, serverZoneValue);
            }else {
                p95Url = String.format(p95UrlTemp, applicationIdName, serverEnvValue, serverZoneVariablePrefix+tbeac.getServerZone()+"\"");
            }
            String resultP95Url = EncodeUrl(P95Average, p95Url);
            EcoServiceRes p95ecoServiceRes = ParseUrl(objectMapper, resultP95Url);
            EcoServiceRes.ServiceData.ServiceResult[] p95Result = p95ecoServiceRes.getData().getResult();

            if (p95Result != null && p95ecoServiceRes.getStatus().equals(success)) {
                for (EcoServiceRes.ServiceData.ServiceResult result : p95Result) {
                    double time = result.getValue()[1];
                    if (time < p95timeNum) {
                        String p95NMum = String.valueOf(time * 1000);
                        ecoServiceDimensionEntity.setOverallAverageP95(p95NMum);
                    } else {
                        String p95NMum = String.valueOf(time);
                        ecoServiceDimensionEntity.setOverallAverageP95(p95NMum);
                    }
                }
            }

            //调用p99
            P99Average.append(msPrefix);
            String p99Url="";
            if(tbeac.getServerZone().isEmpty() || tbeac.getServerZone().equals("")){
                 p99Url = String.format(p99UrlTemp, applicationIdName, serverEnvValue, serverZoneValue);
            }else {
                p99Url = String.format(p99UrlTemp, applicationIdName, serverEnvValue, serverZoneVariablePrefix+tbeac.getServerZone()+"\"");
            }

            String resultP99Url = EncodeUrl(P99Average, p99Url);
            EcoServiceRes p99ecoServiceRes = ParseUrl(objectMapper, resultP99Url);
            EcoServiceRes.ServiceData.ServiceResult[] p99Result = p99ecoServiceRes.getData().getResult();
            if (p99Result != null && p99ecoServiceRes.getStatus().equals(success)) {
                for (EcoServiceRes.ServiceData.ServiceResult result : p99Result) {
                    double time = result.getValue()[1];
                    if (time < p99TimeNum) {
                        String p99NMum = String.valueOf(time * 1000);
                        ecoServiceDimensionEntity.setOverallAverageP99(p99NMum);
                    } else {
                        String p99NMum = String.valueOf(time);
                        ecoServiceDimensionEntity.setOverallAverageP99(p99NMum);
                    }
                }
            }

            totalNum.append(msPrefix);
            String totalUrl="";
            if(tbeac.getServerZone().isEmpty() || tbeac.getServerZone().equals("")){
                 totalUrl = String.format(totalUrlTemp, applicationIdName, serverEnvValue, serverZoneValue);
            }else {
                totalUrl = String.format(totalUrlTemp, applicationIdName, serverEnvValue, serverZoneVariablePrefix+tbeac.getServerZone()+"\"");
            }
            String resultTotalUrl = EncodeUrl(totalNum, totalUrl);
            EcoServiceRes totalServiceRes = ParseUrl(objectMapper, resultTotalUrl);
            EcoServiceRes.ServiceData.ServiceResult[] totalResult = totalServiceRes.getData().getResult();
            if (totalResult != null && p99ecoServiceRes.getStatus().equals(success)) {
                for (EcoServiceRes.ServiceData.ServiceResult result : totalResult) {
                    ecoServiceDimensionEntity.setTotalCalls((long) result.getValue()[1]);
                }
            }


            //调用错误数
            errorNum.append(msPrefix);
            String errorUrl="";
            if(tbeac.getServerZone().isEmpty() || tbeac.getServerZone().equals("")){
                 errorUrl = String.format(errorUrlTemp, applicationIdName, serverEnvValue, serverZoneValue);
            }else {
                errorUrl = String.format(errorUrlTemp, applicationIdName, serverEnvValue, serverZoneVariablePrefix+tbeac.getServerZone()+"\"");
            }
            String resultErrorUrl = EncodeUrl(errorNum, errorUrl);
            EcoServiceRes errorServiceRes = ParseUrl(objectMapper, resultErrorUrl);
            EcoServiceRes.ServiceData.ServiceResult[] errorResult = errorServiceRes.getData().getResult();
            if (errorResult != null && errorServiceRes.getStatus().equals(success)) {
                for (EcoServiceRes.ServiceData.ServiceResult result : errorResult) {
                    ecoServiceDimensionEntity.setNumberOfErrors(String.valueOf(result.getValue()[1]));
                }
            }

            //调用可用性
            methoAvailability.append(msPrefix);
            String availabilityUrl="";
            if(tbeac.getServerZone().isEmpty() || tbeac.getServerZone().equals("")){
                availabilityUrl = String.format(availabilityUrlTemp, applicationIdName, serverEnvValue, serverZoneValue, applicationIdName, serverEnvValue, serverZoneValue, applicationIdName, serverEnvValue, serverZoneValue);
            }else {
                availabilityUrl = String.format(availabilityUrlTemp, applicationIdName, serverEnvValue, serverZoneVariablePrefix+tbeac.getServerZone()+"\"",
                        applicationIdName, serverEnvValue, serverZoneVariablePrefix+tbeac.getServerZone()+"\"", applicationIdName, serverEnvValue,
                        serverZoneVariablePrefix+tbeac.getServerZone()+"\"");
            }
            String resultAvailabilityJson = EncodeUrl(methoAvailability, availabilityUrl);
            EcoServiceRes availabilityServiceRes = ParseUrl(objectMapper, resultAvailabilityJson);
            EcoServiceRes.ServiceData.ServiceResult[] availabilityResult = availabilityServiceRes.getData().getResult();
            if (availabilityResult != null && availabilityServiceRes.getStatus().equals(success)) {
                for (EcoServiceRes.ServiceData.ServiceResult result : availabilityResult) {
                    String s = String.valueOf(result.getValue()[1] * 100) + "%";
                    if (s.split("\\.")[1].length() > 6) {
                        s = s.split("\\.")[0] + "." + s.split("\\.")[1].substring(0, 5) + "%";
                    }
                    ecoServiceDimensionEntity.setServiceAvailability(s);
                }
            }

            //慢查询
            int slowCount = ecoServiceDimensionEntityMapper.countpSlowSearch(ecoServiceDimensionEntity.getApplicationId());
            ecoServiceDimensionEntity.setNumberOfSlowQueries((long) slowCount);
            ecoServiceDimensionEntity.setSaveTime(System.currentTimeMillis());
            ecoServiceDimensionEntity.setServerZone(tbeac.getServerZone());
            ecoServiceDimensionEntityMapper.insert(ecoServiceDimensionEntity);
        }
    }

    private EcoServiceRes ParseUrl(ObjectMapper objectMapper, String resultUrl) {
        try {
            EcoServiceRes ecoServiceRes = objectMapper.readValue(resultUrl, EcoServiceRes.class);
            return ecoServiceRes;
        } catch (JsonProcessingException e) {
            log.info("json解析错误: " + resultUrl);
            return null;
        }
    }

    private String EncodeUrl(StringBuffer preUrl, String encryptionUrl) {
        try {
            String encodeUrl = URLEncoder.encode(encryptionUrl, "UTF-8");
            String currentTime = Long.toString(System.currentTimeMillis());
            String currenttimePrecent = currentTime.substring(0, currentTime.length() - 3) + "." + currentTime.substring(currentTime.length() - 3);
            preUrl.append(encodeUrl).append("&time=").append(currenttimePrecent);
            String jsonString = restTemplate.getForObject(URI.create(preUrl.toString()), String.class);
            preUrl.setLength(0);
            return jsonString;
        } catch (UnsupportedEncodingException e) {
            log.info("url地址请求错误: " + preUrl.toString());
            return null;
        }
    }
}
